# iswm prototype

import logging
logging.basicConfig(filename='/tmp/iswm.log', level=logging.DEBUG)

import sys
import signal
from select import select
import subprocess

import ooxcb
from ooxcb.xproto import *

from base import Object
from screen import Screen

class Core(Object):
    def __init__(self):
        Object.__init__(self)
        
        self.running = False
        self.conn = None
        self.setup = None
        self.screens = []
        self.fds = {'read': {}, 'write': {}, 'error': {}}
        self.select_timeout = 1.0
        
        self.init_xcb()
        self.connect()
        
        for i in xrange(self.setup.roots_len):
            screen = Screen(self, i)
            self.screens.append(screen)
        
        signal.signal(signal.SIGINT, self.stop)
        signal.signal(signal.SIGTERM, self.stop)
        signal.signal(signal.SIGHUP, self.stop)
        
        for screen in self.screens:
            screen.scan()
        
    def connect(self):
        self.conn = ooxcb.connect()
        fd = self.conn.get_file_descriptor()
        self.add_fd_handler('read', fd, self.do_xcb_events)
        self.setup = self.conn.get_setup()
        self.screen = self.setup.roots[self.conn.pref_screen]
    
    def stop(self, *args):
        # TODO
        logging.debug('Stopping')
        self.running = False
    
    def run(self):
        self.running = True
        subprocess.Popen('pidgin', shell=False)
        subprocess.Popen('urxvt', shell=True)
        
        while self.running:
            logging.debug('selecting')
            try:
                rready, wready, xready = select(
                        self.fds['read'].keys(),
                        self.fds['write'].keys(),
                        self.fds['error'].keys(),
                        self.select_timeout
               )
            except Exception, e:
                if e.args[0] == 4:
                    pass
                else:
                    logging.exception(str((e, type(e), dir(e), e.args)))
                    raise
            else:
                for fd in rready:
                    self.fds['read'][fd]()
                for fd in wready:
                    self.fds['write'][fd]()
                for fd in xready:
                    self.fds['error'][fd]()
        
        self.conn.disconnect()
                
                
    def add_fd_handler(self, which_list, fd, callback):
        assert which_list in ('read', 'write', 'error')
        self.fds[which_list][fd] = callback
    
    def init_xcb(self):
        import ooxcb.contrib.icccm
        import ooxcb.contrib.ewmh
        
        ooxcb.contrib.icccm.mixin()
        ooxcb.contrib.ewmh.mixin()
    
    def do_xcb_events(self):
        logging.debug('Got a read')
        while True:
            try:
                ev = self.conn.poll_for_event()
            except Exception, e:
                logging.exception(e)
            else:
                logging.debug('Got an event: %s' % ev)
                if ev is None:
                    break
                try:
                    logging.debug('Dispatching %s to %s.' % (ev.event_name, ev.event_target))
                    ev.dispatch()
                except Exception, e:
                    logging.exception(e)
    
    
if __name__ == "__main__":
    wm = Core()
    wm.run()
